package com.xhwl.centiotdata.suppliersystem.welink.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xhwl.centiotdata.service.cent.IDeviceCentService;
import com.xhwl.centiotdata.service.integrateconfig.DeviceProjSupplierCategoryDTO;
import com.xhwl.centiotdata.suppliersystem.welink.IAttendanceApi;
import com.xhwl.centiotdata.suppliersystem.welink.pojo.Attendance;
import com.xhwl.centiotdata.suppliersystem.welink.pojo.AttendanceQuery;
import com.xhwl.centiotdata.suppliersystem.welink.pojo.ErrorCodeEnum;
import com.xhwl.common.enums.config.IndustryEnum;
import com.xhwl.common.exception.BusinessException;
import com.xhwl.common.exception.DataException;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.common.pojo.cent.device.DeviceProjSupplierCategory;
import com.xhwl.common.pojo.cent.pedes.AttendanceRecord;
import com.xhwl.common.query.cent.device.ProductAccessQuery;
import com.xhwl.common.utils.DateUtils;
import com.xhwl.common.utils.HttpUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * @Author: luyi
 * @Description:
 * @Date: Create in 10:33 2021/11/18
 */
@Component
public class AttendanceApiImpl implements IAttendanceApi {


	@Autowired
	private IDeviceCentService deviceCentService;

	private static Map<Integer, String> TOKEN_MAP = new HashMap<>();

	private static final String host = "https://open.welink.huaweicloud.com";

	private static final String url = "/api/attendance/v3/records";

	private static final Logger log = LoggerFactory.getLogger(AttendanceApiImpl.class);

	@Override
	public ResultJson<Page<AttendanceRecord>> recordList(IndustryEnum industryEnum, Integer projectId, AttendanceQuery attendanceQuery) {

		Map<String, String> header = new HashMap<>();
		header.put("Content-Type", "application/json");

		String s = TOKEN_MAP.get(projectId);
		if(StringUtils.isEmpty(s)){
			s = refreshToken(projectId);
			if(StringUtils.isEmpty(s)){
				return ResultJson.fail("token 获取失败");
			}
		}
		JSONObject jsonObject = getData(projectId, attendanceQuery);
		if(null == jsonObject){
			log.error("接口获取数据失败");
			return ResultJson.fail("接口获取数据失败");
		}

		if("0".equals(jsonObject.get("code"))){
			return ResultJson.success(dataWrapper(jsonObject));
		} else if(ErrorCodeEnum.UNAUTHORIZED.code.equals(jsonObject.get("code")) || "1000".equals(jsonObject.get("errorCode"))){
			// 认证失败
			log.error("认证失败, 重新获取token");
			refreshToken(projectId);
			JSONObject jsonObject1 = getData(projectId, attendanceQuery);
			if("0".equals(jsonObject1.get("code"))){
				return ResultJson.success(dataWrapper(jsonObject1));
			}
			log.error("welink 考勤接口获取失败 {}", jsonObject1);
			return ResultJson.fail("认证失败");
		}else{
			log.error("welink 考勤接口获取失败 {}", jsonObject);
		}
		if(null == jsonObject.get("message")){
			log.error("空数据");
			return ResultJson.fail("");
		}
		return ResultJson.fail(jsonObject.get("message").toString());
	}

	private JSONObject getData(Integer projectId, AttendanceQuery attendanceQuery){
		Map<String, String> header = new HashMap<>();
		header.put("Content-Type", "application/json");
		header.put("x-wlk-Authorization", TOKEN_MAP.get(projectId));
		HttpResponse httpResponse = null;
		try {
			log.info("request param : {}, {}, {}, {}", host, url, header, JSONObject.toJSONString(attendanceQuery));
			httpResponse = HttpUtils.doPost(host, url, header, null, JSONObject.toJSONString(attendanceQuery));
		} catch (Exception e) {
			e.printStackTrace();
		}
		JSONObject jsonObject = new JSONObject();
		if(200 == httpResponse.getStatusLine().getStatusCode()){
			String str = "";
			try {
				str = EntityUtils.toString(httpResponse.getEntity());
			} catch (IOException e) {
				e.printStackTrace();
			}
			jsonObject = JSON.parseObject(str);
		}else{
			try {
				log.error("第三方接口获取异常 {}", EntityUtils.toString(httpResponse.getEntity()));
			} catch (IOException e) {
				e.printStackTrace();
			}
			throw new RuntimeException("第三方接口获取异常");
		}
		return jsonObject;
	}

	private Page dataWrapper(JSONObject jsonObject){
		String string = jsonObject.get("data").toString();
		Integer offset = (int)jsonObject.get("offset");
		Integer limit = (int) jsonObject.get("limit");
		Page<AttendanceRecord> page = new Page<>();
		List<AttendanceRecord> records = new ArrayList<>();
		if(StringUtils.isEmpty(string)){
			return page;
		}
		page.setTotal(Long.valueOf(jsonObject.get("totalCount").toString()));
		List<Attendance> attendances = JSONObject.parseObject(string, new TypeReference<List<Attendance>>(){});
		for (Attendance attendance : attendances) {
			AttendanceRecord attendanceRecord = new AttendanceRecord();
			BeanUtils.copyProperties(attendance, attendanceRecord);
			attendanceRecord.setUserName(attendance.getUserNameCn());
			attendanceRecord.setUserCode(attendance.getUserId());
			attendanceRecord.setDept(attendance.getDeptName());
			attendanceRecord.setIsField(attendance.getIsField().equals("1"));
			attendanceRecord.setIsRange(attendance.getIsRange().equals("1"));
			attendanceRecord.setPunchTime(DateUtils.getFormatDate(attendance.getPunchTime()));
			records.add(attendanceRecord);
		}
		page.setRecords(records);
		page.setCurrent(offset/limit +1);
		page.setSize(limit);
		return page;
	}

	private String refreshToken(Integer projectId){
		log.info("获取 welink token");
		JSONObject authParam = getAuthParam(projectId);
		String token = getToken(authParam.get("client_id").toString(), authParam.get("client_secret").toString());
		this.TOKEN_MAP.put(projectId, token);
		return token;
	}

	@Override
	public String getToken(String clientId, String clientSecret) {
		final String url = "/api/auth/v2/tickets";
		Map<String , String> header = new HashMap<>();
		header.put("Content-Type", "application/json");
		Map<String, String> map = new HashMap<>();
		map.put("client_id", clientId);
		map.put("client_secret", clientSecret);
		String body = JSONObject.toJSONString(map);
		HttpResponse httpResponse = null;
		try {
			httpResponse = HttpUtils.doPost(host, url, header, null, body);
		} catch (Exception e) {
			e.printStackTrace();
		}
		if(200 == httpResponse.getStatusLine().getStatusCode()){
			String str = "";
			try {
				str = EntityUtils.toString(httpResponse.getEntity());
			} catch (IOException e) {
				e.printStackTrace();
			}
			JSONObject jsonObject = JSON.parseObject(str);
			if(jsonObject.get("code").equals("0")){
				String string = jsonObject.get("access_token").toString();
				return string;
			}else{
				log.error("获取token失败 {}", jsonObject);
				return null;
			}

		}else{
			log.error("获取token失败 {}, {}", clientId, clientSecret);
			return null;
		}
	}

	private JSONObject getAuthParam(Integer projectId){
		ProductAccessQuery productAccessQuery = new ProductAccessQuery();
		productAccessQuery.setProductId(18);
		productAccessQuery.setProjectId(projectId);
		List<DeviceProjSupplierCategory> deviceProjSupplierCategories = deviceCentService.listProductAccess(null, productAccessQuery);
		if(CollectionUtils.isEmpty(deviceProjSupplierCategories)){
			throw new BusinessException("获取配置信息失败");
		}
		DeviceProjSupplierCategory deviceProjSupplierCategory = deviceProjSupplierCategories.get(0);
		if(null == deviceProjSupplierCategory){
			throw new BusinessException("获取配置信息失败");
		}
		JSONObject properties = deviceProjSupplierCategory.getProperties();
		if(null == properties){
			log.info("properties 未配置");
			throw new BusinessException("获取配置信息失败");
		}
		return properties;
	}
}
